package com.ruolin.micro.gateway.server.route.resolver;

import com.ruolin.micro.gateway.server.bean.RequestParamResolverHolder;
import com.ruolin.micro.gateway.server.cache.ApplicationGenericServiceCache;
import com.ruolin.micro.gateway.server.constant.FormType;
import com.ruolin.micro.gateway.server.constant.RouterConstant;
import com.ruolin.micro.gateway.server.metadata.MethodRouteMetadata;
import com.ruolin.micro.gateway.server.route.DefaultApplicationRouteLocator;
import com.ruolin.micro.gateway.server.route.RouteDefinitionLocator;
import com.ruolin.micro.gateway.server.route.RpcInvoker;
import com.ruolin.micro.gateway.server.servlet.bean.RouterBeanDefinition;
import com.ruolin.micro.gateway.server.utils.ResponseUtils;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


public abstract class AbstractRequestParameterResolver extends DefaultApplicationRouteLocator implements RequestParameterResolver, RpcInvoker {

    @Autowired
    private RouteDefinitionLocator routeDefinitionLocator;

    public abstract <T extends AbstractRequestParameterResolver> T getResolver();

    public abstract  FormType getFormType();

    public AbstractRequestParameterResolver(){
        RequestParamResolverHolder.getResolverHolder().put(getFormType(), getResolver());
    }

    @Override
    public void doInvoke(HttpServletRequest request, HttpServletResponse response) {
        MethodRouteMetadata methodRouteMetadata = getMethodRouteMetadata(request.getPathInfo(), routeDefinitionLocator.getRouteDefinitions());
        RouterBeanDefinition routerBeanDefinition = getRouterBeanDefinition(request.getPathInfo(), routeDefinitionLocator.getRouteDefinitions());
        String application = routerBeanDefinition.getUri().substring(RouterConstant.SYMBOL.length());
        ReferenceBean<GenericService> serviceReferenceBean = ApplicationGenericServiceCache.getCache(application);
        GenericService genericService = serviceReferenceBean.get();
        FormType formType = FormType.getRequestMethod(request.getMethod());
        AbstractRequestParameterResolver resolver = RequestParamResolverHolder.getResolverHolder().getResolver(formType);
        Object[] args = resolver.resolve(request, response);
        Object result = genericService.$invoke(methodRouteMetadata.getName(), methodRouteMetadata.getParameterTypeArray(), args);
        ResponseUtils.returnJson(response, result);
        response.setStatus(HttpStatus.OK.value());
    }

}